import lkWebSocket from "@/api/base.ts";
import { CommonResult } from "@/api";

type Fun = (data: CommonResult) => void;

class WsSocket {
  /**
   * Websocket 连接
   * @private
   */
  private socket?: WebSocket;

  /**
   * ws连接
   * @private
   */
  private readonly url: string;

  /**
   * token令牌
   */
  private token?: string;

  private receiveCallback: Map<string, Fun> = new Map();

  /**
   * 创建 WsSocket 的实例
   */
  constructor() {
    this.url = lkWebSocket.lkWebSocket;
  }

  /**
   * 连接 Websocket
   */
  connect(token: string) {
    this.token = token;
    this.socket == null && this.loadSocket();
  }

  /**
   * 加载 WebSocket
   */
  loadSocket() {
    const socket = new WebSocket(this.url);
    socket.addEventListener("open", () => {
      this.onOpen();
    });
    socket.addEventListener("message", (event) => {
      this.onMessage(event);
    });
    socket.addEventListener("close", (event) => {
      this.onClose(event);
    });
    socket.addEventListener("error", (event) => {
      this.onError(event);
    });
    this.socket = socket;
    console.log("连接成功...");
  }

  /**
   * 打开连接
   */
  onOpen() {
    console.log("Open: Send Token");
    // 在握手阶段添加Authorization头
    this.socket?.send("Bearer " + this.token);
  }

  /**
   * 接收消息
   * @param event
   */
  onMessage(event: MessageEvent) {
    const data = JSON.parse(event.data);
    // 处理接收到的消息
    this.receiveCallback.forEach((callback) => {
      callback(data as CommonResult);
    });
  }

  /**
   * 关闭连接
   * @param event
   */
  onClose(event: CloseEvent) {
    console.log("连接关闭->", event);
  }

  /**
   * 连接错误
   * @param event
   */
  onError(event: Event) {
    console.log("连接错误->", event);
  }

  /**
   * 聊天发送数据
   * @param message
   */
  send(message: string | object) {
    if (typeof message == "string") {
      this.socket?.send(message);
    } else {
      this.socket?.send(JSON.stringify(message));
    }
  }

  /**
   * 接收消息
   * 设置一个接收消息回调
   * @param id
   * @param callback
   */
  receive(id: string, callback: Fun) {
    this.receiveCallback.set(id, callback);
  }

  /**
   * 关闭连接
   */
  close() {
    this.socket?.close();
  }
}

export default new WsSocket();
